let THREE=require('three');
import Node from './node';
import M from '../../general/utils';
import AabbIntersects from './aabb-intersects';

/**
 * 包围盒动态树检测
 */
export default class AabbDynamicTree extends AabbIntersects{
    constructor(values={}){
        super(values);
    }

    /**
     * 设置叶节点结合的空间尺寸比（值越小层级越浅）
     * @param val {number}
     */
    set grow(val){
        this._grow=val>0.25?0.25:val;
    }

    /**
     * 获取节点长度（数量）
     * @returns {number}
     */
    get length(){
        let c=0;
        for(let i=0;i<this._nodesList.length;i++){
            if(this._nodesList[i]===0)break;
            if(this._nodesList[i]===2)c++;
        }
        return c;
    }

    /**
     * 向树中添加新的形状
     * @param collider {Collider}
     */
    addCollider(collider){
        this._leafCount++;
        switch (this.length){
            case 0:
                this._addFirstNode2(collider);
                break;
            case 1:
                this._addSecondNode2(collider);
                break;
            default:
                this._addRestNode2(collider);
                break;
        }
    }

    /**
     * 更新形状（与更新的形状相关的节点将重构）
     * @param colliders {array}
     */
    updateCollider(...colliders){
        this._clearPairs();
        this._resetChangedAndUpdateList();
        for(let collider of colliders){
            let index=collider.userData.nodeIndex;
            let box=collider.box;
            let min=box.min;
            let max=box.max;
            box.getCenter(this._tempVec);
            let index6=index*6;
            let index3=index*3;
            this._boxList[index6]=min.x;
            this._boxList[index6+1]=min.y;
            this._boxList[index6+2]=min.z;
            this._boxList[index6+3]=max.x;
            this._boxList[index6+4]=max.y;
            this._boxList[index6+5]=max.z;
            this._centerList[index3]=this._tempVec.x;
            this._centerList[index3+1]=this._tempVec.y;
            this._centerList[index3+2]=this._tempVec.z;

            this._enableChangedNode(index);
            this._testNode(index);
        }
        /*box更新时机
         *   交换完毕后更新_changedNodes相应系列（交换前不更新将牺牲精度）yes
         *   交换前更新（完毕后还需更新，可节约的消耗）no
         **/
        if(this._leafCount<3)return;
        this._swapNodes2();
    }

    /**
     * 从树中移除形状
     * @param collider {Collider}
     */
    removeCollider(collider){
        /*
         * 从树中删除叶节点，并更新相应结构
         * 是否有必要按倍率减少列表长度?
         * */
        this._leafCount--;
        let nodeIndex=collider.userData.nodeIndex;
        this._removeNodeFromTree(nodeIndex);
    }

    /**
     * 计算节点结合的得分值（用于选择优先结合的节点对）
     * @param overlap {boolean} 节点对是否交叠
     * @param dis {number} 节点对的距离（平方）
     * @param disMax {number} 与参与检测的节点的最大距离
     * @param disMin {number} 与参与检测的节点的最小距离
     * @param volume {number} 参与检测的节点的子节点数量
     * @returns {number}
     */
    static score(overlap,dis,disMax,disMin,volume){
        let o=overlap?2:1;
        let s=(disMax+disMin)/2/dis;
        let v=1/volume;
        return (s+v)*o;
    }

    /**
     * 测试节点与其所在层（及以下）的其它节点是否交叠
     * @param nodeIndex
     * @param extent
     * @private
     */
    _testNode(nodeIndex,extent=null){
        let ext=extent?extent:this._root;
        if(!ext)return;
        for(let i=0;i<ext.children2.length;i++){
            let ei=ext.children2[i];
            if(ei<0)break;
            let nt=this._nodes[ei];
            if(ei===nodeIndex)continue;
            if(!this._nodeBoxIntersect(nodeIndex,ei))continue;
            if(nt.type===Node.TYPE.LEAF){
                this._recordPair(nodeIndex,ei);
            }else{
                this._testNode(nodeIndex,nt);
            }
        }
    }

    /**
     * 从树中移除节点
     * @param nodeIndex
     * @private
     */
    _removeNodeFromTree(nodeIndex){
        let extentIndex=this._parentList[nodeIndex];
        let extent=this._nodes[extentIndex];
        this._removeNodeChild(extentIndex,nodeIndex);
        this._deleteEmptyNode2(nodeIndex);
        if(extent.children2[1]<0){
            let ntIndex=extent.children2[0];
            if(extentIndex===this._rootIndex){
                this._removeNodeChild(extentIndex,ntIndex);
                this._rootNode2(ntIndex);
                this._deleteEmptyNode2(extentIndex);
                this._nodeBoxUpdate(extentIndex,null,true);
            }else{
                let grandParentIndex=this._parentList[extentIndex];
                this._removeNodeChild(extentIndex,ntIndex);
                this._removeNodeChild(grandParentIndex,extentIndex);
                this._deleteEmptyNode2(extentIndex);
                this._addNodeChild(grandParentIndex,ntIndex);
                this._nodeBoxUpdate(grandParentIndex,null,true);
            }
        }else{
            this._nodeBoxUpdate(extentIndex,null,true);
        }
    }

    /**
     * 更新层级
     * @private
     */
    _swapNodes2(){
        for(let i=0;i<this._changedList.length;i++){
            if(this._changedList[i]<1)break;
            if(this._changedList[i]<2)continue;
            this._checkForNewParent2(i);
        }
    }

    /**
     * 更新指定节点层级
     * @param nodeIndex
     * @returns {*|boolean|boolean}
     * @private
     */
    _checkForNewParent2(nodeIndex){
        /*自下而上逐层查找适宜节点
         * 保持：
         *   是：
         *       条件：当前层范围内，且范围内没有适宜的目标
         *   否：
         *       适宜的目标：
         *           无：
         *               脱离当前层，并结合至父级层查询并结合（当前递归）
         *           有：
         *               branch：进入branch节点自上而下查询并结合（子级递归：_checkInBranch()）
         *               leaf：添加新branch节点作为node和leaf的父级（退出）
         **/
        let extentIndex=this._parentList[nodeIndex];
        let extent=this._nodes[extentIndex];
        /*超出当前层范围*/
        if(!this._nodeBoxContains(extentIndex,nodeIndex)){
            /*如果extent是根节点？当前层查询*/
            if(extentIndex!==this._rootIndex){
                /*与父级的父级交换节点*/
                let grandParentIndex=this._parentList[extentIndex];
                this._removeNodeChild(extentIndex,nodeIndex);
                this._addNodeChild(grandParentIndex,nodeIndex);
                if (extent.children2[1]<0) {
                    let cIndex = extent.children2[0];
                    this._removeNodeChild(extentIndex,cIndex);
                    this._addNodeChild(grandParentIndex,cIndex);
                    this._removeNodeChild(grandParentIndex,extentIndex);
                    this._deleteEmptyNode2(extentIndex);
                }
                /*父级层查询*/
                return this._checkForNewParent2(nodeIndex);
            }
        }
        /*如果当前层只有两个叶节点*/
        if(extent.children2[2]<0){
            if (this._nodes[extent.children2[0]].type === Node.TYPE.LEAF && this._nodes[extent.children2[1]].type === Node.TYPE.LEAF) {
                return true;
            }
        }
        /*当前层查询*/
        let scale2=this._nodeBoxScale(extentIndex);
        let scaleGrow=scale2*this._grow;
        let scoreFacts=[];
        let disMax=Number.NEGATIVE_INFINITY,disMin=Number.POSITIVE_INFINITY;
        for(let i=0;i<extent.children2.length;i++){
            if(extent.children2[i]<0)break;
            let ntIndex=extent.children2[i];
            let nt=this._nodes[ntIndex];
            if(ntIndex===nodeIndex){
                scoreFacts.push(null);
                continue;
            }
            let isOverlapSatisfied=this._nodeBoxIntersect(nodeIndex,ntIndex);
            let dis=this._centerDistanceSquared(nodeIndex,ntIndex);
            let isDensitySatisfied=dis<scaleGrow;
            if(isOverlapSatisfied||isDensitySatisfied){
                if(disMax<dis)disMax=dis;
                if(disMin>dis)disMin=dis;
                let len=1;
                for(let j=0;j<nt.children2.length;j++){
                    if(nt.children2[j]<0)break;
                    len++;
                }
                scoreFacts.push([isOverlapSatisfied,dis,len]);
            }else{
                scoreFacts.push(null);
            }
        }
        let index=-1,_s=0;
        for(let i=0;i<scoreFacts.length;i++){
            let f=scoreFacts[i];
            let s=f?AabbDynamicTree.score(f[0],f[1],disMax,disMin,f[2]):-1;
            if(s>_s){
                index=i;
                _s=s;
            }
        }
        if(index<0){
            /*当前层无适宜目标，保持不变，退出成功*/
            return true;
        }else{
            /*当前层有适宜目标*/
            let ntIndex=extent.children2[index];
            let nt=this._nodes[ntIndex];
            if (nt.type === Node.TYPE.BRANCH) {
                /*与子级交换节点*/
                this._removeNodeChild(extentIndex,nodeIndex);
                this._addNodeChild(ntIndex,nodeIndex);
                this._nodeBoxUpdate(ntIndex,nodeIndex,false);
                /*extent只剩一个子级，删除*/
                if(extent.children2[1]<0){
                    if(extentIndex===this._rootIndex){
                        this._removeNodeChild(extentIndex,ntIndex);
                        this._deleteEmptyNode2(extentIndex);
                        this._rootNode2(ntIndex);
                    }else {
                        let grandParentIndex=this._parentList[extentIndex];
                        this._removeNodeChild(extentIndex,ntIndex);
                        this._addNodeChild(grandParentIndex,ntIndex);
                        this._removeNodeChild(grandParentIndex,extentIndex);
                        this._deleteEmptyNode2(extentIndex);
                    }
                }
                return this._checkForNewParent2(nodeIndex);
            } else {
                let nnIndex = this._createNode(null);
                this._removeNodeChild(extentIndex,nodeIndex);
                this._removeNodeChild(extentIndex,ntIndex);
                this._addNodeChild(nnIndex,ntIndex);
                this._addNodeChild(nnIndex,nodeIndex);
                this._nodeBoxUpdate(nnIndex,null,true);
                this._addNodeChild(extentIndex,nnIndex);
                this._disableChangedNode(ntIndex);
                /*退出成功*/
                return true;
            }
        }
    }

    /**
     * 重设变更列表和更新列表
     * @private
     */
    _resetChangedAndUpdateList(){
        for(let i=0;i<this._changedList.length;i++){
            if(this._changedList[i]<1)break;
            if(this._changedList[i]===2)this._changedList[i]=1;
        }
    }

    /**
     * 添加树的第一个节点
     * @param collider
     * @private
     */
    _addFirstNode2(collider){
        this._rootNode2(this._createNode(collider));
    }

    /**
     * 添加树的第二个节点
     * @param collider
     * @private
     */
    _addSecondNode2(collider){
        let nbIndex=this._createNode(null);
        let nsIndex=this._createNode(collider);

        this._addNodeChild(nbIndex,this._rootIndex);
        this._addNodeChild(nbIndex,nsIndex);
        this._nodeBoxUpdate(nbIndex,null,true);
        this._rootNode2(nbIndex);
    }

    /**
     * 添加其余的节点
     * @param collider
     * @private
     */
    _addRestNode2(collider){
        let nodeIndex=this._createNode(collider);
        if(!this._rectifyRoot2(nodeIndex)){
            return;
        }
        if(!this._insertNode2(nodeIndex,this._root)){
            this._addNodeChild(this._rootIndex,nodeIndex);
            this._nodeBoxUpdate(this._rootIndex,nodeIndex,false);
        }
    }

    /**
     * 矫正根节点
     * @param nodeIndex
     * @returns {boolean}
     * @private
     */
    _rectifyRoot2(nodeIndex){
        let scale2=this._nodeBoxScale(this._rootIndex);
        let disc2=this._centerDistanceSquared(nodeIndex,this._rootIndex);
        let overlap=this._nodeBoxIntersect(nodeIndex,this._rootIndex);
        if((disc2>scale2)&&(!overlap)){
            let npIndex=this._createNode(null);
            this._addNodeChild(npIndex,nodeIndex);
            this._addNodeChild(npIndex,this._rootIndex);
            this._nodeBoxUpdate(npIndex,null,true);
            this._rootNode2(npIndex);
            return false;
        }
        return true;
    }

    /**
     * 向节点插入节点
     * @param nodeIndex
     * @param extent
     * @returns {boolean}
     * @private
     */
    _insertNode2(nodeIndex,extent){
        let extentIndex=extent.index;
        let n6=nodeIndex*6;
        let e6=extentIndex*6;
        this._tempBox[0]=Math.min(this._boxList[n6],this._boxList[e6]);
        this._tempBox[1]=Math.min(this._boxList[n6+1],this._boxList[e6+1]);
        this._tempBox[2]=Math.min(this._boxList[n6+2],this._boxList[e6+2]);
        this._tempBox[3]=Math.max(this._boxList[n6+3],this._boxList[e6+3]);
        this._tempBox[4]=Math.max(this._boxList[n6+4],this._boxList[e6+4]);
        this._tempBox[5]=Math.max(this._boxList[n6+5],this._boxList[e6+5]);

        let dx = this._tempBox[3] - this._tempBox[0];
        let dy = this._tempBox[4] - this._tempBox[1];
        let dz = this._tempBox[5] - this._tempBox[2];
        let scale2= dx * dx + dy * dy + dz * dz;
        let scaleGrow=scale2*this._grow;

        let scoreFacts=[];
        let disMax=Number.NEGATIVE_INFINITY,disMin=Number.POSITIVE_INFINITY;
        for(let i=0;i<extent.children2.length;i++){
            if(extent.children2[i]<0)break;
            let ntIndex=extent.children2[i];
            let nt=this._nodes[ntIndex];
            let isOverlapSatisfied=this._nodeBoxIntersect(nodeIndex,ntIndex);
            let dis=this._centerDistanceSquared(nodeIndex,ntIndex);
            let isDensitySatisfied=dis<scaleGrow;
            if(isOverlapSatisfied||isDensitySatisfied){
                if(disMax<dis)disMax=dis;
                if(disMin>dis)disMin=dis;
                let childCount=0;
                for(let j=0;j<nt.children2.length;j++){
                    if(nt.children2[j]<0)break;
                    childCount++;
                }
                scoreFacts.push([isOverlapSatisfied,dis,childCount+1]);
            }else{
                scoreFacts.push(null);
            }
        }
        let index=-1,_s=0;
        for(let i=0;i<scoreFacts.length;i++){
            let f=scoreFacts[i];
            let s=f?AabbDynamicTree.score(f[0],f[1],disMax,disMin,f[2]):0;
            if(s>_s){
                index=i;
                _s=s;
            }
        }

        if(index!==-1) {
            let ntIndex=extent.children2[index];
            let nt = this._nodes[ntIndex];
            this._nodeBoxUpdate(extentIndex,nodeIndex,false);
            if (nt.type === Node.TYPE.BRANCH) {
                let join = this._insertNode2(nodeIndex, nt);
                if (!join) {
                    this._addNodeChild(ntIndex,nodeIndex);
                    this._nodeBoxUpdate(ntIndex,nodeIndex,false);
                }
            } else {
                let nnIndex = this._createNode(null);
                this._removeNodeChild(extentIndex,ntIndex);
                this._addNodeChild(nnIndex,ntIndex);
                this._addNodeChild(nnIndex,nodeIndex);
                this._nodeBoxUpdate(nnIndex,null,true);
                this._addNodeChild(extentIndex,nnIndex);
            }
            return true;
        }

        return false;
    }

    /**
     * 创建新的节点
     * @param collider
     * @returns {number}
     * @private
     */
    _createNode(collider){
        let node=new Node();
        node.collider=collider;

        let index=0;
        for(let i=0;i<this._nodesList.length;i++){
            if(this._nodesList[i]<2){
                index=i;
                break;
            }
        }

        if(collider){
            collider.userData.nodeIndex=index;
            let box=collider.box;
            box.getCenter(this._tempVec);
            let min=box.min;
            let max=box.max;
            let index6=index*6;
            let index3=index*3;
            this._boxList[index6]=min.x;
            this._boxList[index6+1]=min.y;
            this._boxList[index6+2]=min.z;
            this._boxList[index6+3]=max.x;
            this._boxList[index6+4]=max.y;
            this._boxList[index6+5]=max.z;
            this._centerList[index3]=this._tempVec.x;
            this._centerList[index3+1]=this._tempVec.y;
            this._centerList[index3+2]=this._tempVec.z;
        }
        node.index=index;
        this._nodes[index]=node;
        this._checkVolume();
        this._enableListNode(index);
        this._disableChangedNode(index);
        return index;
    }

    /**
     * 删除空节点（子级及以下都没有叶节点）
     * @param index
     * @private
     */
    _deleteEmptyNode2(index) {
        this._nodes[index].dispose();
        this._nodes[index]=null;
        this._disableListNode(index);
        this._disableChangedNode(index);
    }

    /**
     * 设置根节点
     * @param nodeIndex
     * @private
     */
    _rootNode2(nodeIndex){
        this._root=this._nodes[nodeIndex];
        this._rootIndex=nodeIndex;
        this._parentList[nodeIndex]=-1;
    }

    /**
     * 检查列表长度是否足够并增加列表长度
     * @private
     */
    _checkVolume(){
        if(this._nodes.length>this._volume*0.8){
            this._volume*=2;
            this._resizeList();
        }
    }

    /**
     * 增加列表长度
     * @private
     */
    _resizeList(){
        this._nodesList=M.resizeTypedArray(this._nodesList,this._volume);
        this._changedList=M.resizeTypedArray(this._changedList,this._volume);
        this._boxList=M.resizeTypedArray(this._boxList,this._volume*6);
        this._centerList=M.resizeTypedArray(this._centerList,this._volume*3);
        this._parentList=M.resizeTypedArray(this._parentList,this._volume);
    }

    /**
     * 标记变更列表位置不可用
     * @param nodeIndex
     * @private
     */
    _disableChangedNode(nodeIndex){
        this._changedList[nodeIndex] = 1;
    }

    /**
     * 标记变更列表位置为可用
     * @param nodeIndex
     * @private
     */
    _enableChangedNode(nodeIndex){
        this._changedList[nodeIndex] = 2;
    }

    /**
     * 标记节点列表位置为不可用
     * @param nodeIndex
     * @private
     */
    _disableListNode(nodeIndex){
        this._nodesList[nodeIndex]=1;
    }

    /**
     * 标记节点列表为可用
     * @param nodeIndex
     * @private
     */
    _enableListNode(nodeIndex){
        this._nodesList[nodeIndex]=2;
    }

    /**
     * 记录交叠对
     * @param nodeAIndex
     * @param nodeBIndex
     * @private
     */
    _recordPair(nodeAIndex,nodeBIndex){
        if(!this._overlaps)return;
        this._overlaps.addPair(nodeAIndex,nodeBIndex);
    }

    /**
     * 清除交叠对记录
     * @private
     */
    _clearPairs(){
        if(!this._overlaps)return;
        this._overlaps.clear();
    }

    /**
     * 计算节点之间距离（平方）
     * @param nodeIndex
     * @param tarNodeIndex
     * @returns {number}
     * @private
     */
    _centerDistanceSquared(nodeIndex,tarNodeIndex){
        let n3=nodeIndex*3;
        let t3=tarNodeIndex*3;
        let dx = this._centerList[n3] - this._centerList[t3];
        let dy = this._centerList[n3+1] - this._centerList[t3+1];
        let dz = this._centerList[n3+2] - this._centerList[t3+2];
        return dx * dx + dy * dy + dz * dz;
    }

    /**
     * 计算节点尺寸（平方）
     * @param nodeIndex
     * @returns {number}
     * @private
     */
    _nodeBoxScale(nodeIndex){
        let n6=nodeIndex*6;
        let dx = this._boxList[n6+3] - this._boxList[n6];
        let dy = this._boxList[n6+4] - this._boxList[n6+1];
        let dz = this._boxList[n6+5] - this._boxList[n6+2];
        return dx * dx + dy * dy + dz * dz;
    }

    /**
     * 计算节点之间是否相交
     * @param nodeIndexA
     * @param nodeIndexB
     * @returns {boolean}
     * @private
     */
    _nodeBoxIntersect(nodeIndexA,nodeIndexB) {
        let a6 = nodeIndexA * 6;
        let b6 = nodeIndexB * 6;
        return !(this._boxList[a6 + 3]<this._boxList[b6]||this._boxList[a6]>this._boxList[b6 + 3]||
                this._boxList[a6 + 4]<this._boxList[b6 + 1]||this._boxList[a6 + 1]>this._boxList[b6 + 4]||
                this._boxList[a6 + 5]<this._boxList[b6 + 2]||this._boxList[a6 + 2]>this._boxList[b6 + 5]);
    }

    /**
     * 更新节点包围盒
     * @param nodeIndex
     * @param tarNodeIndex
     * @param reset
     * @private
     */
    _nodeBoxUpdate(nodeIndex,tarNodeIndex,reset=false){
        let n6=nodeIndex*6;
        let n61=n6+1,n62=n6+2,n63=n6+3,n64=n6+4,n65=n6+5;
        let n3=nodeIndex*3;
        if(!reset){
            let t6=tarNodeIndex*6;
            let t61=t6+1,t62=t6+2,t63=t6+3,t64=t6+4,t65=t6+5;
            if(this._boxList[n6]>this._boxList[t6])this._boxList[n6]=this._boxList[t6];
            if(this._boxList[n61]>this._boxList[t61])this._boxList[n61]=this._boxList[t61];
            if(this._boxList[n62]>this._boxList[t62])this._boxList[n62]=this._boxList[t62];
            if(this._boxList[n63]<this._boxList[t63])this._boxList[n63]=this._boxList[t63];
            if(this._boxList[n64]<this._boxList[t64])this._boxList[n64]=this._boxList[t64];
            if(this._boxList[n65]<this._boxList[t65])this._boxList[n65]=this._boxList[t65];
            this._centerList[n3]=(this._boxList[n6]+this._boxList[n63])*0.5;
            this._centerList[n3+1]=(this._boxList[n61]+this._boxList[n64])*0.5;
            this._centerList[n3+2]=(this._boxList[n62]+this._boxList[n65])*0.5;
            return;
        }

        let node=this._nodes[nodeIndex];
        for(let i=0;i<node.children2.length;i++){
            let id=node.children2[i];
            if(id<0)break;

            let i6=id*6;
            let i61=i6+1,i62=i6+2,i63=i6+3,i64=i6+4,i65=i6+5;
            if(i===0){
                this._boxList[n6]=this._boxList[i6];
                this._boxList[n61]=this._boxList[i61];
                this._boxList[n62]=this._boxList[i62];
                this._boxList[n63]=this._boxList[i63];
                this._boxList[n64]=this._boxList[i64];
                this._boxList[n65]=this._boxList[i65];
            }else{
                if(this._boxList[n6]>this._boxList[i6])this._boxList[n6]=this._boxList[i6];
                if(this._boxList[n61]>this._boxList[i61])this._boxList[n61]=this._boxList[i61];
                if(this._boxList[n62]>this._boxList[i62])this._boxList[n62]=this._boxList[i62];
                if(this._boxList[n63]<this._boxList[i63])this._boxList[n63]=this._boxList[i63];
                if(this._boxList[n64]<this._boxList[i64])this._boxList[n64]=this._boxList[i64];
                if(this._boxList[n65]<this._boxList[i65])this._boxList[n65]=this._boxList[i65];
            }
        }
        this._centerList[n3]=(this._boxList[n6]+this._boxList[n63])*0.5;
        this._centerList[n3+1]=(this._boxList[n61]+this._boxList[n64])*0.5;
        this._centerList[n3+2]=(this._boxList[n62]+this._boxList[n65])*0.5;
    }

    /**
     * 计算节点之间是否包含
     * @param nodeIndex
     * @param tarNodeIndex
     * @returns {boolean}
     * @private
     */
    _nodeBoxContains(nodeIndex,tarNodeIndex){
        let n6=nodeIndex*6;
        let t6=tarNodeIndex*6;
        return this._boxList[n6] <= this._boxList[t6] && this._boxList[t6+3] <= this._boxList[n6+3] &&
            this._boxList[n6+1] <= this._boxList[t6+1] && this._boxList[t6+4] <= this._boxList[n6+4] &&
            this._boxList[n6+2] <= this._boxList[t6+2] && this._boxList[t6+5] <= this._boxList[n6+5];
    }

    /**
     * 向节点添加子节点
     * @param nodeIndex
     * @param tarNodeIndex
     * @private
     */
    _addNodeChild(nodeIndex,tarNodeIndex){
        this._nodes[nodeIndex].addChild2(tarNodeIndex);
        this._parentList[tarNodeIndex]=nodeIndex;
    }

    /**
     * 从节点移除子节点
     * @param nodeIndex
     * @param tarNodeIndex
     * @private
     */
    _removeNodeChild(nodeIndex,tarNodeIndex){
        this._nodes[nodeIndex].removeChild2(tarNodeIndex);
    }

    _initVariable(){
        super._initVariable();
        this._grow=0.09;
        this._root=null;
        this._rootIndex=0;
        this._leafCount=0;
        this._tempBox=new Float32Array(6);
        this._changedList=new Uint8Array(this._volume);//0:断点,1:静态,2:动态

        this._boxList=new Float32Array(this._volume*6);
        this._centerList=new Float32Array(this._volume*3);
        this._tempVec=new THREE.Vector3();
        this._parentList=new Int16Array(this._volume);
    }
}